import 'package:get/get.dart';
import 'package:rjpb/page/home/fireAlarm/apis/fireAlarm_service.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/status.dart' as status;
import 'dart:convert'; //使用jsonDecode
import 'package:rjpb/page/home/fireAlarmAlert/controller/fire_alarm_alert_controller.dart';
import 'package:rjpb/config/config.dart'; // 引入配置文件
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:flutter/services.dart';
import 'dart:isolate'; // 用于 ReceivePort 和 IsolateNameServer

import 'dart:ui'; // 用于矩阵变换相关操作
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:rjpb/page/home/controllers/home_controller.dart';
import 'package:flutter/material.dart';
import 'package:rjpb/page/home/profile/apis/logout_api.dart';
import 'dart:async';
import 'package:jovial_svg/jovial_svg.dart'; //svg
import 'package:get_storage/get_storage.dart';
import 'dart:convert'; // 用于解析 JSON
import 'package:flutter/services.dart'; // 用于加载本地文件

const platform = MethodChannel('wake_up_screen');

/// 用于接收来自前台服务的保活 ping 信号
final ReceivePort receivePort = ReceivePort();

/// isolate 名称，用于前台服务与主 isolate 通信

const String isolateName = 'websocket_keep_alive_port';

class FireAlarmPageController extends GetxController {
  // final rows = <Map<String, dynamic>>[].obs; // 存储数据
  // final _currentPage = 1.obs; // 当前页码
  // final _isLoading = false.obs; // 是否正在加载数据
  // final _hasMore = true.obs; // 是否还有更多数据

  var menuData = <Map<String, dynamic>>[].obs; // 菜单数据
  var isLoadingMenu = false.obs; // 加载状态
  var selectedMenuId = ''.obs; // 当前选中的菜单项 ID
  final empty = Rx<bool>(false); //判断巡检左侧下面的数据是不是为空
  final MenuDataEmpty = Rx<bool>(false); //判断三级菜单的数据是不是为空
  var selectedSvgString = ''.obs; // 用于存储选中菜单项的SVG字符串
  var pointData = <Map<String, dynamic>>[].obs; // 用于存储svg图对应的点位信息
  var isLoadingSvg = false.obs; // 右侧SVG 图加载状态

  //火警页面
  var todayFireCount = 0.obs; // 设备离线数
  var PortCount = 0.obs; // 点位总数
  late WebSocketChannel _webSocketChannel; // WebSocket 通道
  Timer? _heartbeatTimer;
  DateTime? _lastPongTime;
  final Duration _heartbeatInterval = const Duration(seconds: 25);
  final Duration _pongTimeout = const Duration(seconds: 35);

  final rows = <Map<String, dynamic>>[].obs; // 存储当前标签页的数据
  final isLoading = false.obs; // 是否正在加载数据
  final _currentPage = 1.obs; // 当前页码
  final _hasMore = true.obs; // 是否还有更多数据
  String _currentTab = "火警"; // 当前标签页
  Rx<int?> deptId = Rx<int?>(null); // 初始为 null，这是部门id,登录账号的人的id,后续登录的时候要拿到这个id

  final selectedLoopNum = Rx<int?>(null); // 保存选中的 loopNum
  final selectedDotNum = Rx<int?>(null); // 保存选中的 dotNum
  final triggerPointTap = RxString(''); // 用于触发点位点击
  final resetMenuViewState = false.obs; // 用于重置菜单视图状态
  final FireAlarmAlertController _alertController =
      Get.find<FireAlarmAlertController>();
  final isLoadingCardTap = false.obs; // 用于控制 loading 状态
  void triggerMenuViewStateReset() {
    resetMenuViewState.toggle(); // 只需改变值即可触发监听
  }

  // 新增变量，用于存储上一次的 alarmSizeSum 值
  int _lastAlarmSizeSum = 0;
  bool _isReconnecting = false;

  //报警点位无效的弹窗
  final showNoDotAlert = false.obs; // 控制是否显示无点位弹窗
  final alertMessage = ''.obs; // 弹窗消息内容

  bool _isWebSocketConnected = false;

  // 一级缓存：内存缓存
  final _svgCache = <String, String>{};
  final _pointsCache = <String, List<Map<String, dynamic>>>{};

  // 二级缓存：持久化存储
  late final GetStorage _storage;

  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
  final shouldBypassPointCache = false.obs; // 是否取缓存
  final _isReceivingAlarms = false.obs;
  final String specialId = '8bcz8e94ex73ltbqieghye90c1m91iq2';
  // 初始化通知插件
  Future<void> initializeNotifications() async {
    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');

    const InitializationSettings initializationSettings =
        InitializationSettings(
      android: initializationSettingsAndroid,
    );

    // await flutterLocalNotificationsPlugin.initialize(initializationSettings);
    await flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
      onDidReceiveNotificationResponse:
          (NotificationResponse notificationResponse) {
        final payload = notificationResponse.payload;
        if (payload != null) {
          if (payload == 'fireAlarm') {
            // Get.toNamed('/fireAlarmPage'); // 替换为你自己的页面路径
            // 切换到火警页面
            final homeController = Get.find<HomeController>();
            homeController.changePage(1);

            // 手动跳转到火警页面
            homeController.pageController.animateToPage(
              1,
              duration: Duration(milliseconds: 300),
              curve: Curves.easeInOut,
            );
            // 等待页面加载完成后触发第一条数据卡片的点击事件
            Future.delayed(Duration(milliseconds: 500), () async {
              await triggerFirstCardTapWithLoading();
            });
          }
        }
      },
    );
  }

  @override
  void onInit() {
    _storage = GetStorage('FireAlarmCache');
    _initStorage();
    super.onInit();
    // 初始化本地通知插件
    initializeNotifications();
    _initializeDeptId();
    loadInitialData(); // 初始化加载数据
    _connectWebSocket(); // 建立 WebSocket 连接
    // fetchPortCount(); // 请求后端接口获取点位总数
    // 监听前台服务的 ping 指令
    receivePort.listen((message) {
      if (message == 'ping') {
        print('[调试] 收到后台服务的 ping 指令，执行 WebSocket 保活');
        reconnectWebSocketIfNeeded();
      }
    });

    IsolateNameServer.registerPortWithName(receivePort.sendPort, isolateName);
  }

  // 初始化存储并启动定时清理
  Future<void> _initStorage() async {
    await GetStorage.init('FireAlarmCache'); // 初始化存储桶
    _startCacheCleanTimer();
  }

  // @override
  // void onClose() {
  //   _webSocketChannel.sink.close(status.goingAway); // 关闭 WebSocket 连接
  //   super.onClose();
  // }
  @override
  void onClose() {
    IsolateNameServer.removePortNameMapping(isolateName);
    receivePort.close();
    super.onClose();
  }

  // 初始化加载数据
  void loadInitialData() async {
    isLoading.value = true; // 开始加载，显示加载动画
    try {
      // 默认加载第一个标签页的数据（火警）
      await loadTabData("火警");

      // 加载菜单数据（如果需要）
      await loadMenuData();
      await fetchPortCount(); // 请求后端接口获取点位总数

      // 其他初始化逻辑
      print("初始化数据加载完成");
    } catch (e) {
      print("初始化加载数据失败: $e");
    } finally {
      isLoading.value = false; // 加载完成，隐藏加载动画
    }
  }

  Future<void> wakeUpScreen() async {
    try {
      await platform.invokeMethod('wakeUp');
    } catch (e) {
      print("唤醒屏幕失败: $e");
    }
  }

  Future<void> _initializeDeptId() async {
    try {
      final userInfo = await LogoutApi.getUserInfo();
      if (userInfo != null && userInfo['user'] != null) {
        print("获取用户信息成功: $userInfo");
        final realDeptId = userInfo['user']['deptId'];
        deptId.value = realDeptId; // 更新 deptId 的值
        print('初始化获取到的 deptId: $realDeptId');
      } else {
        print('获取用户信息失败，无法初始化 deptId');
      }
    } catch (e) {
      print('获取用户信息接口调用失败: $e');
    }
  }

  // 显示无点位弹窗的方法
  void showNoDotAlertDialog() {
    showNoDotAlert.value = true;
    alertMessage.value = '图上无点位';
  }

// 关闭无点位弹窗的方法
  void dismissAlert() {
    showNoDotAlert.value = false;
  }

  //火警左侧下面业务
  // 切换标签页时调用
  void onTabChanged(String tab) {
    _currentTab = tab;
    rows.clear(); // 切换标签时清空当前数据
    _hasMore.value = true; // 重置分页状态
    loadTabData(tab);
  }

  // 加载标签页数据
  Future<void> loadTabData(String tab) async {
    _currentPage.value = 1;
    rows.clear();
    _hasMore.value = true;
    await _fetchData(tab, isRefresh: true);
  }

  // 下拉刷新
  Future<void> refreshTabData(String tab) async {
    _currentPage.value = 1;
    rows.clear();
    _hasMore.value = true;
    await _fetchData(tab, isRefresh: true);
  }

  // 加载更多数据
  Future<void> loadMoreTabData(String tab) async {
    if (isLoading.value || !_hasMore.value) return;
    _currentPage.value++;
    await _fetchData(tab, isRefresh: false);
  }

  // 请求数据
  Future<void> _fetchData(String tab, {required bool isRefresh}) async {
    isLoading.value = true;
    print("要请求数据啦 $tab");
    try {
      final response = await FireAlarmService.fetchAlarmList(
        pageNum: _currentPage.value,
        pageSize: 20,
        infocode: tab,
        today: true,
        // location: "", // 传空字符串
      );

      if (response['code'] == 200) {
        final newRows = response['rows'] as List<dynamic>;

        if (isRefresh) {
          rows.clear();
        }

        if (newRows.isEmpty || newRows.length < 20) {
          _hasMore.value = false;
        }

        rows.addAll(newRows.cast<Map<String, dynamic>>());
        print("非常重要的rows请求数据成功: $rows");
      } else {
        _hasMore.value = false;
        if (isRefresh) rows.clear();
      }
    } catch (e) {
      if (isRefresh) rows.clear();
    } finally {
      isLoading.value = false;
    }
  }

  //火警右侧菜单和svg图以及图标业务
  // 列表项点击事件
  void onListItemTap(int index) {
    final selectedItem = rows[index];
    print('选中项: $selectedItem');
  }

  /// 三级菜单数据
  Future<void> loadMenuData() async {
    isLoadingMenu.value = true;
    try {
      final data = await FireAlarmService.fetchMenuData();
      menuData.value = data;
      MenuDataEmpty.value = menuData.isEmpty;
    } catch (e) {
      print("加载菜单数据异常: $e");
      // menuData.value = [];
      MenuDataEmpty.value = menuData.isEmpty;
    } finally {
      isLoadingMenu.value = false;
      MenuDataEmpty.value = menuData.isEmpty;
    }
  }

  /// 菜单项选中逻辑
  // void onMenuItemSelected(String id) async {
  //   print("嘿嘿嘿");
  //   selectedMenuId.value = id;
  //   print('选中菜单项 ID: $id');

  //   // 开始加载，显示加载动画
  //   isLoadingSvg.value = true;

  //   try {
  //     // 请求接口获取 SVG 字符串
  //     final svgString = await FireAlarmService.fetchSvgData(id);
  //     if (svgString != null) {
  //       selectedSvgString.value = svgString;
  //       print('获取到的 SVG 字符串: $svgString');
  //     } else {
  //       selectedSvgString.value = ''; // 如果请求失败，清空 SVG 字符串
  //       print('未获取到 SVG 字符串');
  //     }

  //     // 请求接口获取点位信息
  //     final points = await FireAlarmService.fetchPointData(id);
  //     pointData.value = points;
  //     print('获取到的点位数据: $points');
  //   } catch (e) {
  //     print('加载 SVG 或点位数据失败: $e');
  //   } finally {
  //     // 加载完成，隐藏加载动画
  //     isLoadingSvg.value = false;
  //   }
  // }
  void onMenuItemSelected(String id, {bool useCache = false}) async {
    print("点击了嘿嘿嘿");
    selectedMenuId.value = id;
    isLoadingSvg.value = true;

    try {
      // // 1. 检查内存缓存
      // if (_tryGetFromMemoryCache(id)) return;

      // // 2. 检查持久化缓存
      // if (await _tryGetFromDiskCache(id)) return;

      // // 3. 网络请求
      // await _fetchFromNetwork(id);

      // 1. SVG 数据永远优先使用缓存
      print('开始重要判断');
      if (_svgCache.containsKey(id)) {
        print('【SVG使用缓存】');
        selectedSvgString.value = _svgCache[id]!;
      } else {
        print('【SVG强制刷新】');
        // final svgString = await FireAlarmService.fetchSvgData(id);
        // if (svgString != null) {
        //   selectedSvgString.value = svgString;
        //   _svgCache[id] = svgString;
        // }
        if (id == '8bcz8e94ex73ltbqieghye90c1m91iq2') {
          final svgString = await _loadLocalSvgString(id);
          if (svgString != null) {
            selectedSvgString.value = svgString;
            _svgCache[id] = svgString;
          }
        } else {
          final svgString = await FireAlarmService.fetchSvgData(id);
          if (svgString != null) {
            selectedSvgString.value = svgString;
            _svgCache[id] = svgString;
          }
        }
      }
      print("重要的值: ${shouldBypassPointCache.value}");
      print("重要的值2: ${useCache}");
      //2. 点位数据根据标志决定是否使用缓存
      if ((!shouldBypassPointCache.value && _pointsCache.containsKey(id)) ||
          useCache) {
        if (_pointsCache.containsKey(id)) {
          pointData.value = _pointsCache[id]!;
          print('【点位使用缓存】');
        } else {
          final points = await FireAlarmService.fetchPointData(id);
          pointData.value = points;
          _pointsCache[id] = points; // 更新缓存
          print('【点位强制刷新】');
        }
      } else {
        final points = await FireAlarmService.fetchPointData(id);
        pointData.value = points;
        _pointsCache[id] = points; // 更新缓存
        print('【点位强制刷新】');

        // if (id != '8bcz8e94ex73ltbqieghye90c1m91iq2') {
        //   shouldBypassPointCache.value = false; //读缓存
        // }
      }
    } catch (e) {
      print('加载失败: $e');
      _fallbackToCache(id);
    } finally {
      isLoadingSvg.value = false;
    }
  }

  //加载本地svg
  Future<String?> _loadLocalSvgString(String id) async {
    try {
      // 加载本地 JSON 文件
      final String jsonString =
          await rootBundle.loadString('assets/svgs/local_svg_data.json');
      final Map<String, dynamic> svgData = json.decode(jsonString);

      // 根据 ID 获取对应的 SVG 字符串
      return svgData[id] as String?;
    } catch (e) {
      print('加载本地 SVG 数据失败: $e');
      return null;
    }
  }

  // 尝试从内存获取
  bool _tryGetFromMemoryCache(String id) {
    if (_svgCache.containsKey(id) && _pointsCache.containsKey(id)) {
      selectedSvgString.value = _svgCache[id]!;
      pointData.value = _pointsCache[id]!;
      print('【缓存命中】内存');
      return true;
    }
    return false;
  }

  // 尝试从磁盘获取
  Future<bool> _tryGetFromDiskCache(String id) async {
    try {
      final cached = _storage.read(id);
      if (cached != null && cached['svg'] != null && cached['points'] != null) {
        selectedSvgString.value = cached['svg'];
        pointData.value = List<Map<String, dynamic>>.from(cached['points']);
        _updateMemoryCache(id, cached['svg'], cached['points']);
        print('【缓存命中】磁盘');
        return true;
      }
    } catch (e) {
      print('读取磁盘缓存失败: $e');
    }
    return false;
  }

  // 从网络获取
  Future<void> _fetchFromNetwork(String id) async {
    print('【缓存未命中】请求网络...');
    final results = await Future.wait([
      FireAlarmService.fetchSvgData(id),
      FireAlarmService.fetchPointData(id),
    ], eagerError: true);

    final svgString = results[0] as String?;
    final points = results[1] as List<Map<String, dynamic>>?;

    if (svgString == null || points == null) throw Exception('数据不完整');

    selectedSvgString.value = svgString;
    pointData.value = points;
    _updateAllCaches(id, svgString, points);
  }

  // 更新所有缓存
  void _updateAllCaches(
      String id, String svg, List<Map<String, dynamic>> points) {
    _updateMemoryCache(id, svg, points);
    _updateDiskCache(id, svg, points);
  }

  // 更新内存缓存
  void _updateMemoryCache(
      String id, String svg, List<Map<String, dynamic>> points) {
    // 简单LRU策略
    if (_svgCache.length >= 20) _svgCache.remove(_svgCache.keys.first);
    if (_pointsCache.length >= 20) _pointsCache.remove(_pointsCache.keys.first);

    _svgCache[id] = svg;
    _pointsCache[id] = points;
  }

  // 更新磁盘缓存
  void _updateDiskCache(
      String id, String svg, List<Map<String, dynamic>> points) {
    _storage.write(id, {
      'svg': svg,
      'points': points,
      'timestamp': DateTime.now().millisecondsSinceEpoch,
    });
  }

  // 降级方案
  void _fallbackToCache(String id) {
    if (_tryGetFromMemoryCache(id)) return;

    // 尝试强制从磁盘读取（忽略时效性）
    try {
      final cached = _storage.read(id);
      if (cached != null) {
        selectedSvgString.value = cached['svg'] ?? '';
        pointData.value =
            List<Map<String, dynamic>>.from(cached['points'] ?? []);
      }
    } catch (e) {
      selectedSvgString.value = '';
      pointData.value = [];
    }
  }

  // 定时清理
  void _startCacheCleanTimer() {
    Timer.periodic(Duration(hours: 6), (_) {
      final now = DateTime.now().millisecondsSinceEpoch;
      final keys = _storage.getKeys();

      for (final key in keys) {
        final data = _storage.read(key);
        if (data is Map && data['timestamp'] != null) {
          if (now - data['timestamp'] > 7 * 24 * 60 * 60 * 1000) {
            _storage.remove(key);
          }
        }
      }
    });
  }

  // 清空缓存
  void clearCache() {
    _svgCache.clear();
    _pointsCache.clear();
    _storage.erase();
  }

  /// 根据当前状态判断是否需要重连
  void reconnectWebSocketIfNeeded() {
    print('目前websocket状态: $_isWebSocketConnected');
    if (!_isWebSocketConnected) {
      print('[WebSocket保活] 检测到断线，尝试重连...');
      _attemptReconnect();
      print('[WebSocket保活] 当前已在重连中，跳过...');
      // 当前已断开，尝试重连
      // print('[WebSocket保活] 检测到断线，尝试重连...');
      // if (!_isReconnecting) {
      //   _attemptReconnect();
      // } else {
      //   print('[WebSocket保活] 当前已在重连中，跳过...');
      // }
    } else {
      print('[WebSocket保活] 连接正常，无需重连');
    }
  }

  Future<void> showFireAlarmNotification(String message) async {
    const AndroidNotificationDetails androidPlatformChannelSpecifics =
        AndroidNotificationDetails(
      'fire_alarm_channel_id', // 唯一标识
      '火警报警通道', // 通道名称
      channelDescription: '用于显示火警通知',
      importance: Importance.max,
      priority: Priority.high,
      fullScreenIntent: true,
      playSound: true,
      sound: RawResourceAndroidNotificationSound('alarm_sound'), // 不要带扩展名
      enableVibration: true,
      ticker: '火警报警',
    );

    const NotificationDetails platformChannelSpecifics = NotificationDetails(
      android: androidPlatformChannelSpecifics,
    );

    await flutterLocalNotificationsPlugin.show(
      0,
      '收到新的火警信息！',
      message,
      platformChannelSpecifics,
      payload: 'fireAlarm', // 用于跳转判断
    );
  }

  // 建立 WebSocket 连接
  void _connectWebSocket() async {
    _webSocketChannel = WebSocketChannel.connect(
      // Uri.parse('ws://14.103.242.73:16692/ws'),
      Uri.parse('$webSocketUrl/ws'),
    );

    print('WebSocket 连接成功');
    _isWebSocketConnected = true; // 设置连接状态为 true

    // 初始化 pong 时间
    _lastPongTime = DateTime.now();

    // 连接成功后，立即发送初始消息（deptId 可能是 null）
    _sendDeptId(deptId.value);
    // try {
    //   final userInfo = await LogoutApi.getUserInfo();
    //   if (userInfo != null && userInfo['user'] != null) {
    //     final realDeptId = userInfo['user']['deptId'];
    //     deptId.value = realDeptId; // 更新 deptId 的值
    //     print('获取到的 deptId: $realDeptId');
    //     _sendDeptId(realDeptId); // 发送真实的 deptId
    //   } else {
    //     print('获取用户信息失败，无法获取 deptId');
    //   }
    // } catch (e) {
    //   print('获取用户信息接口调用失败: $e');
    // }

    // 监听 deptId 变化，动态更新服务器
    deptId.listen((newDeptId) {
      if (_webSocketChannel != null) {
        _sendDeptId(newDeptId); // deptId 变化时，发送新值
      }
    });

    // 开始心跳逻辑
    _startHeartbeat();

    // 监听服务器消息
    _webSocketChannel.stream.listen((message) async {
      print('收到消息: $message');
      if (message == 'hay') {
        _lastPongTime = DateTime.now();
        print('[WebSocket] 收到 hay 响应: $_lastPongTime');
        return;
      }
      try {
        final data = jsonDecode(message);
        // 判断 alarmSizeSum 是否存在并是一个列表
        if (data['alarmSizeSum'] != null && data['alarmSizeSum'] is List) {
          // _isReceivingAlarms.value = true; // 标记正在接收报警
          shouldBypassPointCache.value = true; // 点位绕过缓存
          final currentAlarmSizeSum = data['alarmSizeSum'][0] ?? 0;

          // 更新 todayFireCount
          todayFireCount.value = currentAlarmSizeSum;
          print("当前 currentAlarmSizeSum: $currentAlarmSizeSum");
          print("上一次 _lastAlarmSizeSum: $_lastAlarmSizeSum");
          print("当前路由: ${Get.currentRoute}");
          print("当前 rows: $rows");
          // 判断是否需要显示弹窗
          // if (rows.isNotEmpty &&
          //     (currentAlarmSizeSum > _lastAlarmSizeSum) &&
          //     Get.currentRoute != '/login') {
          //   print("有火警信息了！${rows}");
          //   _alertController.showAlert(
          //       '收到新的火警信息！', List<Map<String, dynamic>>.from(rows));
          // }
          if (rows.isNotEmpty &&
              (currentAlarmSizeSum > _lastAlarmSizeSum) &&
              Get.currentRoute != '/login') {
            print("有火警信息了！$rows");
            await wakeUpScreen(); // 点亮屏幕
            // 播放通知（后台锁屏有效）
            await showFireAlarmNotification("有新的火警信息，请注意查看！");
            // _isReceivingAlarms.value = false; // 标记正在接收报警
          }

          // 更新 _lastAlarmSizeSum
          _lastAlarmSizeSum = currentAlarmSizeSum;
        }

        _currentTab = "火警";
        await loadTabData("火警");
      } catch (e) {
        print('WebSocket 数据解析错误: $e');
      }
    }, onError: (error) {
      print('WebSocket 错误: $error');
      _isWebSocketConnected = false; // 设置连接状态为 false
      _stopHeartbeat();
      _attemptReconnect();
    }, onDone: () {
      print('WebSocket 连接已关闭');
      _isWebSocketConnected = false; // 设置连接状态为 false
      _stopHeartbeat();
      _attemptReconnect();
    });
  }

  // 心跳定时器逻辑
  void _startHeartbeat() {
    _heartbeatTimer?.cancel();

    _heartbeatTimer = Timer.periodic(Duration(seconds: 25), (_) {
      if (_webSocketChannel != null) {
        try {
          _webSocketChannel!.sink.add('hello');
          print('[WebSocket] 发送 hello: ${DateTime.now()}');

          // 检查是否超时未收到 pong
          if (_lastPongTime != null) {
            final diff = DateTime.now().difference(_lastPongTime!);
            if (diff > Duration(seconds: 35)) {
              print('[WebSocket] 超过 35 秒未收到 pong，执行重连...');
              _stopHeartbeat();
              _isWebSocketConnected = false;
              _attemptReconnect();
            }
          }
        } catch (e) {
          print('[WebSocket] 发送 hello 失败: $e');
          _stopHeartbeat();
          _isWebSocketConnected = false;
          _attemptReconnect();
        }
      }
    });
  }

  void _stopHeartbeat() {
    _heartbeatTimer?.cancel();
    _heartbeatTimer = null;
  }

  // 尝试重连的方法
  void _attemptReconnect() {
    if (_isReconnecting) return; // 如果已经在重连中，则直接返回
    _isReconnecting = true;
    _heartbeatTimer?.cancel();
    _webSocketChannel?.sink.close();
    // _webSocketChannel = null;

    const retryInterval = Duration(seconds: 5); // 每次重连的间隔时间
    print('尝试在 $retryInterval 后重连 WebSocket...');

    Future.delayed(retryInterval, () {
      print('正在重连 WebSocket...');
      _connectWebSocket(); // 重新建立连接
      _isReconnecting = false; // 重连完成后重置状态
    });
  }

// 发送 deptId 到服务器
  void _sendDeptId(int? deptId) {
    if (_webSocketChannel != null) {
      final message = jsonEncode({'deptId': deptId});
      _webSocketChannel.sink.add(message);
      print('已发送 deptId: $message');
    }
  }

  // 请求后端接口获取点位总数
  Future<void> fetchPortCount() async {
    try {
      final count = await FireAlarmService.fetchDotCount();
      print('点位总数: $count');
      PortCount.value = count['data']; // 更新串口异常数
    } catch (e) {
      print('获取点位总数失败: $e');
    }
  }

  //点击左侧tabs下面的卡片逻辑
  Future<void> onCardTap(int cardId, int loopNum, int dotNum) async {
    print("哈哈哈哈哈哈哈哈哈哈哈哈");
    // shouldBypassPointCache.value = true; // 点位绕过缓存
    try {
      // 保存 loopNum 和 dotNum
      selectedLoopNum.value = loopNum;
      selectedDotNum.value = dotNum;
      // 请求后端接口 /alarm/getfloor
      final response = await FireAlarmService.fetchFloorData(cardId);
      if (response['code'] == 200 && response['data'] != null) {
        print('获取楼层数据成功: ${response['data']}');
        if (response['data']['spare3'] == "NoDot") {
          print("没有点位数据了！");
          // 触发视图状态重置
          triggerMenuViewStateReset();
          onMenuItemSelected('8bcz8e94ex73ltbqieghye90c1m91iq2');
          showNoDotAlertDialog(); // 显示弹窗
        } else {
          final floorId = response['data']['id']; // 获取楼层 ID
          print('楼层 ID: $floorId');
          // 触发视图状态重置
          triggerMenuViewStateReset();

          // 设置三级菜单的选中 ID
          onMenuItemSelected(floorId.toString());
        }
      } else {
        print('获取楼层数据失败: ${response['msg']}');
      }
    } catch (e) {
      print('请求楼层数据失败: $e');
    }
  }

  // 在FireAlarmPageController中添加
  void checkAndTriggerPointTap(List<Map<String, dynamic>> points) {
    if (selectedLoopNum.value != null && selectedDotNum.value != null) {
      for (final point in points) {
        final pointLoopNum = point['loopNum'];
        final pointDotNum = point['dotNum'];
        final pointState = point['state'];

        if (pointLoopNum == selectedLoopNum.value &&
            pointDotNum == selectedDotNum.value &&
            pointState == 1) {
          // 这里需要通知视图层触发点击事件
          // 我们可以通过一个Rx变量来传递需要触发的点位ID
          triggerPointTap.value = point['id'];
          break;
        }
      }
    }
  }

  // 触发第一条数据卡片的点击事件
  // Future<void> triggerFirstCardTapWithLoading() async {
  //   print("触发第一条数据卡片点击事件 ${rows}");
  //   if (rows.isEmpty) {
  //     print("没有数据，无法触发卡片点击事件");
  //     return;
  //   }

  //   try {
  //     isLoadingCardTap.value = true; // 显示 loading
  //     final firstRow = rows.first;
  //     final cardId = firstRow['id'];
  //     final loopNum = firstRow['loopNum'];
  //     final dotNum = firstRow['dotNum'];

  //     print("触发第一条数据卡片点击事件: ID=$cardId, loopNum=$loopNum, dotNum=$dotNum");
  //     await Future.delayed(Duration(seconds: 1)); // 模拟点击事件的处理时间
  //     onCardTap(cardId, loopNum, dotNum); // 调用卡片点击事件处理逻辑
  //   } finally {
  //     isLoadingCardTap.value = false; // 隐藏 loading
  //   }
  // }

  // 触发第一条数据卡片的点击事件
  Future<void> triggerFirstCardTapWithLoading() async {
    print("开始触发第一条数据卡片点击事件");
    isLoadingCardTap.value = true; // 立即显示 loading

    try {
      // 等待数据加载完成的逻辑
      const maxRetry = 10; // 最大重试次数 (10*500ms=5秒超时)
      int retryCount = 0;

      while (rows.isEmpty && retryCount < maxRetry) {
        print("数据为空，等待中... (${retryCount + 1}/$maxRetry)");
        await Future.delayed(Duration(milliseconds: 500));
        retryCount++;
      }

      if (rows.isEmpty) {
        print("等待超时，数据仍未加载完成");
        return;
      }

      final firstRow = rows.first;
      final cardId = firstRow['id'];
      final loopNum = firstRow['loopNum'];
      final dotNum = firstRow['dotNum'];

      print("触发第一条数据卡片点击事件: ID=$cardId, loopNum=$loopNum, dotNum=$dotNum");
      await Future.delayed(Duration(seconds: 1)); // 模拟点击事件的处理时间
      await onCardTap(cardId, loopNum, dotNum); // 调用卡片点击事件处理逻辑
    } catch (e) {
      print("触发卡片点击事件时发生错误: $e");
    } finally {
      isLoadingCardTap.value = false; // 最终隐藏 loading
      print("点击事件处理完成");
    }
  }

  // 预加载常用 SVG 和点位数据
  Future<void> preloadCommonSvgs() async {
    // const popularIds = [
    //   '8bcz8e94ex73ltbqieghye90c1m91iq2',
    //   '6i5qw3rgym26o7prjc4f4dpvngklnhw5',
    //   'f7xgpxdn7pwpjnh98se5xeuk6b8xutku',
    //   'jcuwf806fbb3o06gsngo077c2vxtz09p',
    //   'sjilbvgq0tgi72q378lzqsme5mdgo963',
    //   '4k024huyefv9oog1lbz3oyfafpkpcpud',
    //   'gkgowwwfh4sob5inx873qpp717sxpihk',
    //   '00gu3xzkcizzjxkk5cyry57ws6am7od9',
    //   'uy9v11mcuxxub4skbwygcnfvibz2y0if',
    //   '26qsziuud8b04dryo2ll3xi0i3gtguy5',
    //   'uplc53tuffs73pvdclx8llcjiqd3m2ei',
    //   'wnvdrf85educkwwfehfy2hu8ogwqxidu',
    //   'xjupz758dkbwofgjr4e5y7nqlc022ikd',
    //   '1ffr9mfrjvdn15eytl7npobnnpquqo51',
    //   'b8pk977piypk63y26dhogub4mpbmc9b4'
    // ]; // 常用菜单 ID

    const popularIds = [
      '8bcz8e94ex73ltbqieghye90c1m91iq2',
      '6i5qw3rgym26o7prjc4f4dpvngklnhw5',
      'f7xgpxdn7pwpjnh98se5xeuk6b8xutku',
      'jcuwf806fbb3o06gsngo077c2vxtz09p',
      'sjilbvgq0tgi72q378lzqsme5mdgo963',
      '4k024huyefv9oog1lbz3oyfafpkpcpud'
    ];

    for (final id in popularIds) {
      try {
        // 并行获取 SVG 和点位数据
        final results = await Future.wait([
          FireAlarmService.fetchSvgData(id),
          FireAlarmService.fetchPointData(id),
        ], eagerError: true);

        if (results[0] != null && results[1] != null) {
          _svgCache[id] = results[0] as String;
          _pointsCache[id] = results[1] as List<Map<String, dynamic>>;
          print('预加载成功: $id');
        }
      } catch (e) {
        print('预加载 $id 失败: $e');
      }
    }
  }
}
